package com.demon.framework.boot.autoconfigure.sentinel;

import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
import com.alibaba.csp.sentinel.datasource.FileWritableDataSource;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ClassUtils;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * 默认基于 文件 持久化 规则
 *
 * @author Demon-HY
 * @description
 * @date 2020/7/27 16:18
 */
@Configuration
@ConditionalOnProperty("spring.cloud.sentinel.transport.dashboard")
public class FileRuleAutoConfiguration {

    @Value("${spring.cloud.sentinel.persistence.filename.flow:flowRule.json}")
    private String flowFileName;
    @Value("${spring.cloud.sentinel.persistence.filename.authority:authorityRule.json}")
    private String authorityFileName;
    @Value("${spring.cloud.sentinel.persistence.filename.degrade:degradeRule.json}")
    private String degradeFileName;
    @Value("${spring.cloud.sentinel.persistence.filename.system:systemRule.json}")
    private String systemFileName;

    @PostConstruct
    public void init() throws Exception {
        Class<?>[] allInterfacesForClass = ClassUtils.getAllInterfacesForClass(WritableDataSource.class);
        if (allInterfacesForClass.length == 1) {
            settingFlowRule();
            settingSystemRule();
            settingDegradeRule();
            settingAuthorityRule();
        }
    }

    /**
     * 设置授权规则
     *
     * @throws java.io.FileNotFoundException
     */
    private void settingAuthorityRule() throws java.io.FileNotFoundException {
        // 保存了限流规则的文件的地址
        String ruleFileName = authorityFileName;
        // 加载文件规则数据源
        FileRefreshableDataSource<List<AuthorityRule>> ruleDataSource =
                new FileRefreshableDataSource<>(ruleFileName, source -> JSON.parseObject(source, new TypeReference<List<AuthorityRule>>() {
        }));
        // 将Property注册到 RuleManager 中去
        AuthorityRuleManager.register2Property(ruleDataSource.getProperty());

        //设置持久化数据源
        FileWritableDataSource<List<AuthorityRule>> fileWritableDataSource =
                new FileWritableDataSource<>(ruleFileName, JSON::toJSONString);
        WritableDataSourceRegistry.registerAuthorityDataSource(fileWritableDataSource);
    }

    /**
     * 设置降级规则
     *
     * @throws java.io.FileNotFoundException
     */
    private void settingDegradeRule() throws java.io.FileNotFoundException {
        // 保存了限流规则的文件的地址
        String ruleFileName = degradeFileName;
        // 加载文件规则数据源
        FileRefreshableDataSource<List<DegradeRule>> ruleDataSource =
                new FileRefreshableDataSource<>(ruleFileName, source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
        }));
        // 将Property注册到 RuleManager 中去
        DegradeRuleManager.register2Property(ruleDataSource.getProperty());

        //设置持久化数据源
        FileWritableDataSource<List<DegradeRule>> fileWritableDataSource =
                new FileWritableDataSource<>(ruleFileName, JSON::toJSONString);
        WritableDataSourceRegistry.registerDegradeDataSource(fileWritableDataSource);
    }

    /**
     * 设置系统规则
     *
     * @throws java.io.FileNotFoundException
     */
    private void settingSystemRule() throws java.io.FileNotFoundException {
        // 保存了限流规则的文件的地址
        String ruleFileName = systemFileName;
        // 加载文件规则数据源
        FileRefreshableDataSource<List<SystemRule>> ruleDataSource =
                new FileRefreshableDataSource<>(ruleFileName, source ->
                        JSON.parseObject(source, new TypeReference<List<SystemRule>>() {})
                );
        // 将Property注册到 RuleManager 中去
        SystemRuleManager.register2Property(ruleDataSource.getProperty());

        //设置持久化数据源
        FileWritableDataSource<List<SystemRule>> fileWritableDataSource =
                new FileWritableDataSource<>(ruleFileName, JSON::toJSONString);
        WritableDataSourceRegistry.registerSystemDataSource(fileWritableDataSource);
    }

    /**
     * 设置流控规则
     *
     * @throws java.io.FileNotFoundException
     */
    private void settingFlowRule() throws java.io.FileNotFoundException {
        // 保存了限流规则的文件的地址
        String ruleFileName = flowFileName;
        // 加载文件规则数据源
        FileRefreshableDataSource<List<FlowRule>> ruleDataSource =
                new FileRefreshableDataSource<>(ruleFileName, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
        }));
        // 将Property注册到 RuleManager 中去
        FlowRuleManager.register2Property(ruleDataSource.getProperty());

        //设置持久化数据源
        FileWritableDataSource<List<FlowRule>> fileWritableDataSource =
                new FileWritableDataSource<>(ruleFileName, JSON::toJSONString);
        WritableDataSourceRegistry.registerFlowDataSource(fileWritableDataSource);
    }
}
